package com.loveprogrammer.eternity.factory;

import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.loveprogrammer.eternity.action.BaseAction;
import com.loveprogrammer.eternity.enums.*;
import com.loveprogrammer.eternity.factory.template.EquipmentTemplate;
import com.loveprogrammer.eternity.factory.template.SuitTemplate;
import com.loveprogrammer.eternity.model.Hero;
import com.loveprogrammer.eternity.model.Monster;
import com.loveprogrammer.eternity.model.product.Equipment;
import com.loveprogrammer.eternity.model.product.Things;
import com.loveprogrammer.eternity.model.product.eggs.Egg;
import com.loveprogrammer.eternity.model.product.equipment.Weapon;
import com.loveprogrammer.eternity.utils.RandomBalance;
import org.apache.poi.util.StringUtil;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version 1.0.0
 * @description: 装备工厂
 * @author: eric
 * @date: 2022-08-09 10:34
 **/
public class EquipmentFactory extends BaseAction {

    private static List<EquipmentTemplate> allEquipmentTemplates;
    private static List<EquipmentTemplate> weaponTemplates;
    private static Map<Integer,EquipmentTemplate> weaponTemplateIdMap;

    // 套装
    private static List<SuitTemplate> suitTemplates;
    private static List<EquipmentTemplate> suitEquipmentTemplates;
    private static Map<Integer,SuitTemplate> suitTemplateMap;

    // 固定装备
    private static List<EquipmentTemplate> constantEquipmentTemplate;
    private static Map<Integer,EquipmentTemplate> constantMap;

    private static Map<Integer,List<EquipmentTemplate>> weaponTypeGroup;

    static {
        try {
            // 读取配置文件，然后加载到weaponTemplates中
            ClassLoader classLoader = EquipmentFactory.class.getClassLoader();

            InputStream inputStream = classLoader.getResourceAsStream("equipments/weapon.json");

            BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();

            String inputStr;
            while ((inputStr = streamReader.readLine()) != null)
                responseStrBuilder.append(inputStr);

            weaponTemplates = JSONArray.parseArray(responseStrBuilder.toString(),EquipmentTemplate.class);
            weaponTemplateIdMap = weaponTemplates.stream().collect(Collectors.toMap(EquipmentTemplate::getId, e->e));

            weaponTypeGroup = weaponTemplates.stream().collect(Collectors.groupingBy(EquipmentTemplate::getWeaponType));

            if(allEquipmentTemplates == null){
                allEquipmentTemplates = new ArrayList<>();
            }
            allEquipmentTemplates.addAll(weaponTemplates);

            // 加载其他的普通装备
            String path = classLoader.getResource("equipments").getFile();//注意getResource("")里面是空字符串
            File file = new File(path);
            File[] files = file.listFiles();
            for (File f : files) {
                if(f.getName().equals("weapon.json")){
                    continue;
                }
                String fileName = "equipments/" + f.getName();
                inputStream = classLoader.getResourceAsStream(fileName);

                streamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                responseStrBuilder = new StringBuilder();

                String str;
                while ((str = streamReader.readLine()) != null)
                    responseStrBuilder.append(str);

                List<EquipmentTemplate> equipmentTemplates = JSONArray.parseArray(responseStrBuilder.toString(),EquipmentTemplate.class);
                allEquipmentTemplates.addAll(equipmentTemplates);
            }

            // 加载套装
            String suitPath = classLoader.getResource("exclusive_equipments/suit").getFile();//注意getResource("")里面是空字符串
            File suitFolder = new File(suitPath);
            File[] suitFiles = suitFolder.listFiles();
            for (File f : suitFiles) {
                String fileName = "exclusive_equipments/suit/" + f.getName();
                inputStream = classLoader.getResourceAsStream(fileName);

                streamReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                responseStrBuilder = new StringBuilder();

                String str;
                while ((str = streamReader.readLine()) != null)
                    responseStrBuilder.append(str);

                SuitTemplate suitTemplate = JSON.parseObject(responseStrBuilder.toString(),SuitTemplate.class);
                if(suitTemplates == null){
                    suitTemplates = new ArrayList<>();
                }
                suitTemplates.add(suitTemplate);
                List<EquipmentTemplate> equipments = suitTemplate.getEquipments();
                if(suitEquipmentTemplates == null){
                    suitEquipmentTemplates = new ArrayList<>();
                }
                suitEquipmentTemplates.addAll(equipments);
            }
            suitTemplateMap = suitTemplates.stream().collect(Collectors.toMap(SuitTemplate::getId, e -> e));

            // 加载固定装备
            inputStream = classLoader.getResourceAsStream("exclusive_equipments/constant/equipment.json");
            assert inputStream != null;
            streamReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            responseStrBuilder = new StringBuilder();

            String str;
            while ((str = streamReader.readLine()) != null)
                responseStrBuilder.append(str);

            constantEquipmentTemplate = JSONArray.parseArray(responseStrBuilder.toString(),EquipmentTemplate.class);
            //
            constantMap = constantEquipmentTemplate.stream().collect(Collectors.toMap(EquipmentTemplate::getId, e -> e));

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

    public static Equipment createEquipment(Monster monster,
                                            QualityEnum qualityEnum){
        Equipment result;
        // 根据怪物等级，找到对应的装备; 去掉等级过高的装备
        List<EquipmentTemplate> templates = allEquipmentTemplates.stream().filter(e -> e.getLevel() <= monster.getLevel()).collect(Collectors.toList());
        List<EquipmentTemplate> suitTemplates = suitEquipmentTemplates.stream().filter(e -> e.getLevel() <= monster.getLevel()).collect(Collectors.toList());

        // 如果是套装
        if(qualityEnum == QualityEnum.绿色){
            eventManager.notifyMessage("发现绿色装备", 1);
            if(suitTemplates.size() > 0){
                EquipmentTemplate suitTemplate = suitTemplates.get(new Random().nextInt(suitTemplates.size()));
                if(suitTemplate.getType().equalsIgnoreCase(EquipmentEnum.WEAPON.getCode())){
                    result = getWeapon(suitTemplate,qualityEnum);
                }else{
                    // 不是武器的话都一样
                    result = getOtherEquipment(suitTemplate,qualityEnum);
                }
                result.setSuitId(suitTemplate.getSuitId());
                return result;
            }else{
                qualityEnum = QualityEnum.暗金;
            }
        }
        // 随机找到一个装备模板
        EquipmentTemplate equipmentTemplate = templates.get(new Random().nextInt(templates.size()));
        // 找到装备的品质
        if(equipmentTemplate.getType().equalsIgnoreCase(EquipmentEnum.WEAPON.getCode())){
            result = getWeapon(equipmentTemplate,qualityEnum);
        }else{
            // 不是武器的话都一样
            result = getOtherEquipment(equipmentTemplate,qualityEnum);
        }
        // 添加词缀
        return AffixFactory.setAffix(result);
    }

    private static Weapon getWeapon(EquipmentTemplate equipmentTemplate, QualityEnum qualityEnum) {
        Weapon weapon = new Weapon(equipmentTemplate.getName(),equipmentTemplate.getType(),
                equipmentTemplate.getDesc(), EquipmentEnum.WEAPON,
                WeaponTypeEnum.getByCode(equipmentTemplate.getWeaponType()),qualityEnum,equipmentTemplate.getId());
        // TODO 品质越高，浮动越小
        weapon.setGoods_id(equipmentTemplate.getId());
        weapon.setLevel(equipmentTemplate.getLevel());
        weapon.setArmature(calculate(equipmentTemplate.getArmature(),qualityEnum));
        weapon.setStrength(calculate(equipmentTemplate.getStrength(),qualityEnum));
        weapon.setSpeed(calculate(equipmentTemplate.getSpeed(),qualityEnum));
        weapon.setConstitution(calculate(equipmentTemplate.getConstitution(),qualityEnum));
        weapon.setTechnique(calculate(equipmentTemplate.getTechnique(),qualityEnum));
        weapon.setHp(calculate(equipmentTemplate.getHp(),qualityEnum));
        weapon.setMagic(calculate(equipmentTemplate.getMagic(),qualityEnum));
        weapon.setSpeed(calculate(equipmentTemplate.getSpeed(),qualityEnum));
        weapon.setEvasion(calculate(equipmentTemplate.getEvasion(),qualityEnum));
        weapon.setFortune(calculate(equipmentTemplate.getFortune(),qualityEnum));
        weapon.setPoisonResistance(calculate(equipmentTemplate.getPoisonResistance(),qualityEnum));
        weapon.setFlameResistance(calculate(equipmentTemplate.getFlameResistance(),qualityEnum));
        weapon.setThunderResistance(calculate(equipmentTemplate.getThunderResistance(),qualityEnum));
        weapon.setIceResistance(calculate(equipmentTemplate.getIceResistance(),qualityEnum));
        return weapon;
    }


    public static Equipment getOtherEquipment(EquipmentTemplate equipmentTemplate, QualityEnum qualityEnum) {
        Equipment equipment = new Equipment(equipmentTemplate.getName(),equipmentTemplate.getType(),
                equipmentTemplate.getDesc(),EquipmentEnum.getByCode(equipmentTemplate.getType()),qualityEnum,equipmentTemplate.getId());
        // 品质越高，浮动越小
        equipment.setGoods_id(equipmentTemplate.getId());
        equipment.setLevel(equipmentTemplate.getLevel());
        equipment.setArmature(calculate(equipmentTemplate.getArmature(),qualityEnum));
        equipment.setStrength(calculate(equipmentTemplate.getStrength(),qualityEnum));
        equipment.setSpeed(calculate(equipmentTemplate.getSpeed(),qualityEnum));
        equipment.setConstitution(calculate(equipmentTemplate.getConstitution(),qualityEnum));
        equipment.setTechnique(calculate(equipmentTemplate.getTechnique(),qualityEnum));
        equipment.setHp(calculate(equipmentTemplate.getHp(),qualityEnum));
        equipment.setMagic(calculate(equipmentTemplate.getMagic(),qualityEnum));
        equipment.setSpeed(calculate(equipmentTemplate.getSpeed(),qualityEnum));
        equipment.setEvasion(calculate(equipmentTemplate.getEvasion(),qualityEnum));
        equipment.setFortune(calculate(equipmentTemplate.getFortune(),qualityEnum));
        // 四种元素的抗性
        equipment.setPoisonResistance(calculate(equipmentTemplate.getPoisonResistance(),qualityEnum));
        equipment.setFlameResistance(calculate(equipmentTemplate.getFlameResistance(),qualityEnum));
        equipment.setThunderResistance(calculate(equipmentTemplate.getThunderResistance(),qualityEnum));
        equipment.setIceResistance(calculate(equipmentTemplate.getIceResistance(),qualityEnum));
        return equipment;
    }

    private static int calculate(String data, QualityEnum qualityEnum) {
        if(StringUtils.isEmpty(data)){
            return 0;
        }
        String[] split = data.split("-");
        int min = Integer.parseInt(split[0]);
        int max = Integer.parseInt(split[1]);
        int add = max - min;
        if(add > 1){
            switch (qualityEnum){
                case 黄色:
                    min = min + add/5;
                    break;
                case 紫色:
                    min = min + add/4;
                    break;
                case 红色:
                    min = min + add/3;
                    break;
                case 暗金:
                    min = min + add/2;
                    break;
                default:
                    break;
            }
        }
        if(max > min) {
            // 根据品质改变最大最小值
            return min + new Random().nextInt(max - min);
        }else if (max == min){
            return max;
        }
        return 0;
    }


    public static void main(String[] args) {
        for (EquipmentTemplate template : constantEquipmentTemplate) {
            System.out.println(template.toString());
        }

    }

    public static List<EquipmentTemplate> getWeaponTemplates() {
        return weaponTemplates;
    }

    public static Weapon getWeaponById(int id,QualityEnum qualityEnum){
        EquipmentTemplate template = weaponTemplateIdMap.get(id);
        Weapon weapon = getWeapon(template, qualityEnum);
        AffixFactory.setAffix(weapon);
        return weapon;
    }

    public static Equipment getEquipmentById(int id,QualityEnum qualityEnum){
        EquipmentTemplate template = allEquipmentTemplates.get(id);
        Equipment otherEquipment = getOtherEquipment(template, qualityEnum);
        AffixFactory.setAffix(otherEquipment);
        return otherEquipment;
    }

    public static SuitTemplate getSuitById(int id){
        return suitTemplateMap.get(id);
    }

    public static List<Equipment> getRandomList(int num) {
        List<Equipment> result = new ArrayList<>();
        int size = allEquipmentTemplates.size();
        int sizeWeapon = weaponTemplates.size();
        EquipmentTemplate equipmentTemplate;
        EquipmentTemplate template;
        for (int i = 0; i < num; i++) {
            // 品质随机 确定装备的品类
            QualityEnum equipQuality = RandomBalance.findQuality(0, 40, 40, 30, 2, 1, 0);
            // 至少有一个武器
            if(i < 1){
                template = weaponTemplates.get(new Random().nextInt(sizeWeapon));
                result.add(getWeapon(template, equipQuality));
            }else {
                equipmentTemplate = allEquipmentTemplates.get(new Random().nextInt(size));
                result.add(getOtherEquipment(equipmentTemplate, equipQuality));
            }
        }
        return result;
    }

    public static Equipment createEquipment(Hero hero, QualityEnum equipQuality, EquipmentEnum equipmentEnum) {
        List<EquipmentTemplate> templateList = allEquipmentTemplates.stream()
                .filter(e -> e.getType().equals(equipmentEnum.getCode()))
                .filter(e -> e.getLevel() <= hero.getLevel())
                .collect(Collectors.toList());

        if(templateList.isEmpty()){
            return null;
        }
        if(equipmentEnum.getCode().equalsIgnoreCase(EquipmentEnum.WEAPON.getCode())){
            // 还要根据武器
            templateList = templateList.stream().filter(e -> e.getWeaponType() == hero.getTemplate().getWeaponType())
                    .collect(Collectors.toList());
            if(templateList.isEmpty()){
                return null;
            }
            EquipmentTemplate template = templateList.get(new Random().nextInt(templateList.size()));
            return getWeapon(template,equipQuality);
        }else{
            EquipmentTemplate template = templateList.get(new Random().nextInt(templateList.size()));
            return getOtherEquipment(template,equipQuality);
        }
    }

    public static Equipment getSpecialById(int id, QualityEnum qualityEnum) {
        EquipmentTemplate equipmentTemplate = constantMap.get(id);
        Equipment equipment;
        if(equipmentTemplate.getType().equalsIgnoreCase("weapon")){
            equipment = getWeapon(equipmentTemplate,qualityEnum);
        }else {
            equipment = getOtherEquipment(equipmentTemplate, qualityEnum);
        }
        // 固定四个前缀
        AffixFactory.setAffix(equipment,4);
        return equipment;
    }

    public static Weapon getWeaponByHero(Hero hero, int minLevel, int maxLevel, String goodsTemplateId) {
        int weaponType = hero.getTemplate().getWeaponType();
        List<EquipmentTemplate> templates = weaponTemplates.stream().filter(e -> e.getWeaponType() == weaponType && e.getLevel() >= minLevel && e.getLevel() <= maxLevel).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(templates)){
            return null;
        }
        Collections.shuffle(templates);
        EquipmentTemplate equipmentTemplate = templates.get(0);
        QualityEnum qualityEnum = QualityEnum.getById(Integer.parseInt(goodsTemplateId));
        return getWeapon(equipmentTemplate,qualityEnum);
    }

    public static Equipment getEquipmentByHero(Hero hero, int minLevel, int maxLevel, String goodsTemplateId) {
        List<EquipmentTemplate> templates = allEquipmentTemplates.stream()
                .filter(e -> e.getWeaponType() == 0 && e.getLevel() >= minLevel && e.getLevel() <= maxLevel).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(templates)){
            return null;
        }
        Collections.shuffle(templates);
        EquipmentTemplate equipmentTemplate = templates.get(0);
        QualityEnum qualityEnum = QualityEnum.getById(Integer.parseInt(goodsTemplateId));
        return getOtherEquipment(equipmentTemplate,qualityEnum);
    }
}
